package com.zhz.common.utils;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.zhz.common.tool.mybatisplus.base.core.contract.Page;
import com.zhz.common.tool.mybatisplus.base.core.contract.PageParam;
import com.zhz.common.tool.mybatisplus.base.core.contract.R;
import com.zhz.common.tool.mybatisplus.base.core.contract.SortParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.*;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Function;

/**
 * 转换类
 * @author zhouhengzhe
 */
public class Converter {
    private static final Logger log = LoggerFactory.getLogger(Converter.class);
    private static final String REFLECT_ERROR = "反射获取转换对象异常";
    private static final String COMMA = ",";

    private Converter() {
    }

    public static <T> R<T> copy(R source, Class<T> target) {
        if (source == null) {
            return null;
        } else {
            T object = copy(source.getData(), target);
            return new R(object);
        }
    }

    public static <T> Page<T> copy(Page source, Class<T> target) {
        if (source == null) {
            return null;
        } else {
            List<T> targetList = copy((Collection)source.getList(), target);
            long total = source.getTotal();
            return new Page(targetList, total);
        }
    }

    public static <T, S> PageParam<T> copy(PageParam<S> source, Class<T> target) {
        if (source == null) {
            return null;
        } else {
            PageParam<T> pageParam = new PageParam(source.getPage(), source.getLimit());
            T targetObject = copy(source.getParam(), target);
            pageParam.setParam(targetObject);
            pageParam.setSorts(copy((Collection)source.getSorts(), SortParam.class));
            return pageParam;
        }
    }

    public static void mapToObject(Map map, Object object) {
        if (object != null && map != null) {
            BeanWrapper beanWrapper = new BeanWrapperImpl(object);
            PropertyValues propertyValues = new MutablePropertyValues(map);
            beanWrapper.setPropertyValues(propertyValues, true, true);
        }

    }

    public static String changeColumnToFieldName(String columnName) {
        String[] array = columnName.split("_");
        StringBuilder sb = null;
        String[] var3 = array;
        int var4 = array.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String cn = var3[var5];
            cn = cn.toLowerCase();
            if (sb == null) {
                sb = new StringBuilder(cn);
            } else {
                sb.append(cn.substring(0, 1).toUpperCase()).append(cn.substring(1));
            }
        }

        return sb != null ? sb.toString() : null;
    }

    public static Map<String, Object> objectToMap(Object obj) {
        Collection<String> ignoredFieldCol = new HashSet();
        return objectToMap(obj, (Collection)ignoredFieldCol);
    }

    public static Map<String, Object> objectToMap(Object obj, Collection<String> ignoredFieldCol) {
        if (obj == null) {
            return null;
        } else {
            Map<String, Object> map = new HashMap();
            if (obj instanceof String) {
                map.put((String)obj, obj);
                return map;
            } else {
                objectToMap(obj, map, ignoredFieldCol);
                return map;
            }
        }
    }

    public static void objectToMap(Object object, Map map) {
        if (object != null && map != null) {
            objectToMap(object, map, (Collection)null);
        }

    }

    public static void listMapToListObject(List<Map<String, Object>> mapList, List objectList, Class clazz) {
        if (CollUtil.isNotEmpty(mapList) && objectList != null) {
            Iterator var3 = mapList.iterator();

            while(var3.hasNext()) {
                Map map = (Map)var3.next();
                Object object = gainInstanceByReflect(clazz);
                mapToObject(map, object);
                objectList.add(object);
            }
        }

    }

    public static void listObjectToListObject(List sourceList, List targetList, Class targetClass) {
        if (CollUtil.isNotEmpty(sourceList) && targetList != null) {
            Iterator var3 = sourceList.iterator();

            while(var3.hasNext()) {
                Object source = var3.next();
                Object target = gainInstanceByReflect(targetClass);
                BeanUtils.copyProperties(source, target);
                targetList.add(target);
            }
        }

    }

    public static String listToString(List<String> list) {
        return listToString(list, ",");
    }

    public static String listToString(List<String> list, String separator) {
        return listToString(list, separator, (String)null);
    }

    public static String listToString(List<String> list, String separator, String surround) {
        StringBuilder builder = new StringBuilder();
        if (CollUtil.isNotEmpty(list)) {
            int i = 0;
            Iterator var5 = list.iterator();

            while(var5.hasNext()) {
                String str = (String)var5.next();
                if (i++ > 0) {
                    builder.append(separator);
                }

                if (surround != null) {
                    builder.append(surround).append(str).append(surround);
                } else {
                    builder.append(str);
                }
            }
        }

        return builder.toString();
    }

    public static Object gainInstanceByReflect(Class clazz) {
        String className = clazz.getName();
        return gainInstanceByReflect(className);
    }

    private static Object gainInstanceByReflect(String className) {
        Object target = null;

        try {
            target = Class.forName(className).newInstance();
        } catch (IllegalAccessException | ClassNotFoundException | InstantiationException var3) {
            log.error("反射获取转换对象异常", var3);
        }

        return target;
    }

    public static void objectToObject(Object source, Object target) {
        objectToObject(source, target, false, true, true);
    }

    public static void objectToObject(Object source, Object target, boolean ignoreNull) {
        objectToObject(source, target, ignoreNull, false, false);
    }

    public static void objectToObject(Object source, Object target, boolean ignoreNull, boolean withCreateInfo, boolean withUpdateInfo) {
        if (source != null && target != null) {
            List<String> ignorePropertiesList = new ArrayList();
            if (!withCreateInfo) {
                ignorePropertiesList.add("creator");
                ignorePropertiesList.add("creatorCode");
                ignorePropertiesList.add("createTime");
            }

            if (!withUpdateInfo) {
                ignorePropertiesList.add("updater");
                ignorePropertiesList.add("updaterCode");
                ignorePropertiesList.add("updateTime");
            }

            if (ignoreNull) {
                ignoreNull(source, ignorePropertiesList);
            }

            String[] ignorePropertiesArray = new String[ignorePropertiesList.size()];
            BeanUtils.copyProperties(source, target, (String[])ignorePropertiesList.toArray(ignorePropertiesArray));
        }
    }

    private static void ignoreNull(Object source, List<String> ignorePropertiesList) {
        Field[] fields = source.getClass().getDeclaredFields();

        try {
            Field[] var3 = fields;
            int var4 = fields.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                Field field = var3[var5];
                field.setAccessible(true);
                if (field.get(source) == null) {
                    ignorePropertiesList.add(field.getName());
                }
            }
        } catch (IllegalAccessException | IllegalArgumentException var7) {
            log.error("反射获取转换对象异常", var7);
        }

    }

    public static void objectToObject(Object source, Object target, boolean ignoreNull, boolean isUpdate) {
        objectToObject(source, target, ignoreNull, !isUpdate, true);
    }

    public static void transMap2Bean(Map<String, Object> map, Object obj) {
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            PropertyDescriptor[] var4 = propertyDescriptors;
            int var5 = propertyDescriptors.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                PropertyDescriptor property = var4[var6];
                String key = property.getName();
                if (map.containsKey(key)) {
                    Object value = map.get(key);
                    Method setter = property.getWriteMethod();
                    setter.invoke(obj, value);
                }
            }
        } catch (Exception var11) {
            log.error("Map --> Bean Error {} {}", new Object[]{map, obj, var11});
        }

    }

    public static <T, Q> T of(Q q, Class<T> targetClass) {
        if (Objects.isNull(q)) {
            return null;
        } else {
            T t = BeanUtils.instantiateClass(targetClass);
            objectToObject(q, t, true, true, true);
            return t;
        }
    }

    public static <T> T ofMap(Map<String, Object> map, Class<T> targetClass) {
        if (!Objects.isNull(map) && !map.isEmpty()) {
            T t = BeanUtils.instantiateClass(targetClass);
            mapToObject(map, t);
            return t;
        } else {
            return null;
        }
    }

    public static <T, Q> List<T> ofList(List<Q> sources, Class<T> targetClass) {
        if (CollUtil.isEmpty(sources)) {
            return new ArrayList();
        } else {
            List<T> targetList = new ArrayList();
            listObjectToListObject(sources, targetList, targetClass);
            return targetList;
        }
    }

    public static <T> List<T> ofMapList(List<Map<String, Object>> sources, Class<T> targetClass) {
        if (CollUtil.isEmpty(sources)) {
            return new ArrayList();
        } else {
            List<T> targetList = new ArrayList();
            listMapToListObject(sources, targetList, targetClass);
            return targetList;
        }
    }

    public static String[] getNullPropertyNames(Object source) {
        BeanWrapper src = new BeanWrapperImpl(source);
        PropertyDescriptor[] pds = src.getPropertyDescriptors();
        Set<String> emptyNames = new HashSet();
        PropertyDescriptor[] var4 = pds;
        int var5 = pds.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            PropertyDescriptor pd = var4[var6];
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }

        String[] result = new String[emptyNames.size()];
        return (String[])emptyNames.toArray(result);
    }

    public static void copy(Object source, Object target) {
        if (!ObjectUtils.isEmpty(source) && !ObjectUtils.isEmpty(target)) {
            String[] nullPropertyNames = getNullPropertyNames(source);
            BeanUtils.copyProperties(source, target, nullPropertyNames);
        }
    }

    public static <T> T copy(Object source, Class<T> target) {
        return copy(source, target, (Class)null);
    }

    public static <T> T copy(Object source, Class<T> target, Class<?> targetSuper) {
        if (source == null) {
            return null;
        } else {
            Object targetObject = null;

            try {
                targetObject = target.newInstance();
                BeanUtils.copyProperties(source, targetObject, targetSuper);
            } catch (Exception var5) {
                log.error("convert error {} {} {}", new Object[]{source, target, targetSuper, var5});
            }

            return (T) targetObject;
        }
    }

    public static <T> List<T> copy(Collection<?> sourceList, Class<T> target) {
        if (sourceList == null) {
            return null;
        } else {
            ArrayList targetList = new ArrayList(sourceList.size());

            try {
                Iterator iterator = sourceList.iterator();

                while(iterator.hasNext()) {
                    Object source = iterator.next();
                    T targetObject = target.newInstance();
                    BeanUtils.copyProperties(source, targetObject);
                    targetList.add(targetObject);
                }
            } catch (Exception var6) {
                log.error("convert error {} {} {}", new Object[]{sourceList, target, var6});
            }

            return targetList;
        }
    }

    public static <T> T copy(Object source, Class<T> target, String... ignoreProperties) {
        if (source == null) {
            return null;
        } else {
            Object targetObject = null;

            try {
                targetObject = target.newInstance();
                BeanUtils.copyProperties(source, targetObject, ignoreProperties);
            } catch (Exception var5) {
                log.error("convert error {} {}", new Object[]{source, target, var5});
            }

            return (T) targetObject;
        }
    }

    public static <T> List<T> copy(Collection<?> sourceList, Class<T> target, String... ignoreProperties) {
        if (sourceList == null) {
            return null;
        } else {
            ArrayList targetList = new ArrayList(sourceList.size());

            try {
                Iterator var4 = sourceList.iterator();

                while(var4.hasNext()) {
                    Object source = var4.next();
                    T targetObject = target.newInstance();
                    BeanUtils.copyProperties(source, targetObject, ignoreProperties);
                    targetList.add(targetObject);
                }
            } catch (Exception var7) {
                log.error("convert error {} {}", new Object[]{sourceList, target, var7});
            }

            return targetList;
        }
    }

    public static <F, T> List<T> transform(Collection<F> fromList, Function<? super F, ? extends T> function) {
        if (fromList != null && !fromList.isEmpty()) {
            function.getClass();
            Collection<? extends T> output = Collections2.transform(fromList, function::apply);
            return Lists.newArrayList(output);
        } else {
            return Lists.newArrayList();
        }
    }

    public static <T, S> Page<T> transform(Page<S> source, Function<? super S, ? extends T> mapper) {
        if (source == null) {
            return Page.empty();
        } else {
            List<T> targetList = transform((Collection)source.getList(), mapper);
            long total = source.getTotal();
            return new Page(targetList, total);
        }
    }

    public static void objectToMap(Object source, Map target, Collection<String> ignoredFieldCol) {
        Assert.notNull(source, "source is required");
        Assert.notNull(target, "target is required");
        if (Objects.isNull(ignoredFieldCol)) {
            ignoredFieldCol = new HashSet();
        }

        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(source.getClass());
            PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
            PropertyDescriptor[] var8 = pds;
            int var9 = pds.length;

            for(int var10 = 0; var10 < var9; ++var10) {
                PropertyDescriptor pd = var8[var10];
                Method method = pd.getWriteMethod();
                if (method != null) {
                    String key = pd.getName();
                    if (!((Collection)ignoredFieldCol).contains(key)) {
                        Method getter = pd.getReadMethod();
                        Object val = getter != null ? getter.invoke(source) : null;
                        target.put(key, val);
                    }
                }
            }
        } catch (InvocationTargetException | IllegalAccessException | IntrospectionException var13) {
            log.error("反射获取转换对象异常", var13);
        }

    }
}
